#! /usr/bin/php
<?php
$alphabet = 'QWERTYUIOPASDFGHJKLZXCVBNMqwertyuiopasdfghjklzxcvbnm1234567890';
$VMajor = 2;
$VMinor = 1;
$VRev = "\$Revision: 41 $";
preg_match("~([\d]+)~",$VRev,$VRevm);
$VRev = $VRevm[1];
$Version = "{$VMajor}.{$VMinor}.{$VRev}";
$path = GetPath();
$argl = array(
	"chan" => array(
		"required"	=> 1,
		"hasvalue"	=> 1,
		"default"	=> "2ch.ru",
		"desc"		=> "Chan module name",
	),
	"mode" => array(
		"required"	=> 1,
		"hasvalue"	=> 1,
		"default"	=> "wipe",
		"desc"		=> "Workmode (Supported : wipe, bump, upload, save, load)",
	),
	"board" => array(
		"required"	=> 1,
		"hasvalue"	=> 1,
		"default"	=> "b",
		"desc"		=> "Chan target board",
	),
	"post-set" => array(
		"required"	=> 1,
		"hasvalue"	=> 1,
		"default"	=> "nigra",
		"desc"		=> "Set(s) of pics and text to use. Divided with commas.",
	),
	"password" => array(
		"required"	=> 1,
		"hasvalue"	=> 1,
		"default"	=> "TheFuckinWipe",
		"desc"		=> "Password for post deletion.",
	),
	"random-password" => array(
		"required"	=> 0,
		"hasvalue"	=> 0,
		"desc"		=> "Password is random string instead \$password if specified.",
	),	
	"sage" => array(
		"required"	=> 0,
		"hasvalue"	=> 0,
		"desc"		=> "Sage thread if specified.",
	),
	"silent" => array(
		"required"	=> 0,
		"hasvalue"	=> 0,
		"desc"		=> "Do not post any text if specified.",
	),
	"credits" => array(
		"required"	=> 0,
		"hasvalue"	=> 0,
		"desc"		=> "Include version in text if specified.",
	),	
	"say-captcha" => array(
		"required"	=> 0,
		"hasvalue"	=> 0,
		"desc"		=> "Include captcha in text if specified.",
	),	
	"no-pic" => array(
		"required"	=> 0,
		"hasvalue"	=> 0,
		"desc"		=> "Do not post pictures if specified.",
	),
	"cites" => array(
		"required"	=> 0,
		"hasvalue"	=> 1,
		"default"	=> "",
		"desc"		=> "Enable \$CITE\$ string replacement with one of the following services : bash.org,bash.org.ru,fortune",
	),
	"captcha" => array(
		"required"	=> 0,
		"hasvalue"	=> 1,
		"desc"		=> "If specified, will try to use anti-captcha module.",
	),		
	"check-pages" => array(
		"required"	=> 0,
		"hasvalue"	=> 1,
		"default"	=> 2,
		"desc"		=> "Check this many pages in bump mode to see if thread needs bump.",
	),
	"skip" => array(
		"required"	=> 0,
		"hasvalue"	=> 1,
		"default"	=> 0,
		"desc"		=> "Skip this many images/posts for upload/load modes.",
	),
);

include($path."includes/mod_common.php");
include($path."includes/mod_cli.php");
include($path."includes/mod_core.php");
include($path."includes/mod_images.php");

define("PostResult_OK",		0);
define("PostResult_FloodLimit",	1);
define("PostResult_Banned",	2);
define("PostResult_PicExist",	3);
define("PostResult_NoThread",	4);
define("PostResult_Timeout",	5);
define("PostResult_DBError",	6);
define("PostResult_BadFile",	7);
define("PostResult_MsgTooLong",	8);
define("PostResult_WrongPass",	9);
define("PostResult_CaptchaWrong",10);
define("PostResult_Captcha",	11);
define("PostResult_WakabaErr",	253);
define("PostResult_HTTPErr",	254);
define("PostResult_UnknownErr",	255);
function GetPath()
{
	global $argv;
	$path = dirname(realpath($argv[0]));
	$ls   = substr($path,-1,1);
	if ($ls != '/' AND $ls != "\\")
		$path.='/';
	return $path;
}
function MakePic($f)
{
	global $args,$ThreadID,$ThreadName,$path;
	if ($args['alter'] == 'quick')
	{
		$e = explode('.',$f);
		$e = strtolower(end($e));
		$r = ImageAlterQuick($f,$path."tmp/".$ThreadID.floor(microtime(1)*100).".".$e);
	}
	else if ($args['alter'] == 'stealth' OR $args['alter'] == 'string')
	{
		$im = OpenImage($f);
		$black = imagecolorresolve($im,0,0,0);
		$w = imagesx($im);
		$h = imagesy($im);		
		if (($w > $args['max-size']) OR ($h > $args['max-size']))
		{
			$w2 = $args['max-size'];
			$h2 = $args['max-size'];
			if ($w < $h)
				$w2 = floor(($args['max-size'] / $h) * $w);
			else
				$h2 = floor(($args['max-size'] / $w) * $h);
		}
		else if (($w < $args['min-size']) OR ($h < $args['min-size']))
		{
			$w2 = $args['min-size'];
			$h2 = $args['min-size'];
			if ($w < $h)
				$w2 = floor(($args['min-size'] / $h) * $w);
			else
				$h2 = floor(($args['min-size'] / $w) * $h);
		}
		if ($w2)
		{
			$im = ImageResize($im,$w2,$h2);
		}
		
		if ($args['alter'] == 'stealth')
		{
			$im = ImageAlterStealth($im,$args['stealth']);
		}
		else
		{
			$im = ImageAlterString($im,"{$ThreadId} {$ThreadName} ".floor(microtime(1)*100));
		}
		$r = $path."tmp/".$ThreadID.floor(microtime(1)*100).".jpg";
		imagejpeg($im,$r,$args['jpg-quality']);
		imagedestroy ($im);				
	}
	else
	{
		$r = $f;
	}
	return $r;
}
function DeletePost($TID,$p)
{
	global $args,$Threads,$request,$callback,$callbackp,$useragents,$proxy,$tids,$password,$v;
	switch($p['task'])
	{
		case "init":
			$v['request'] = GetChanDeleteFields($tids,$pass);
		case "delete":
			if (ProxyGet())
			{
				$url = GetChanDeleteUrl($args['board']);
				EchoMsgDebug("DeletePost @ $url $v[request]",2);
				DoHTTPRequestPM(array(
					'url'		=> $url,
					'data'		=> $v['request'],
					'proxytype'	=> $proxy['proxytype'],
					'proxy'		=> $proxy['proxy'],
					'timeout'	=> $args['timeout'],
					'ua'		=> $useragents[$args['user-agent']],
					'params'	=> array('task'=>'done'),
					'debug'		=> ($args['debug']>2)?($args['debug']-2):0,
					));
			}
			else
			{
				QueueThread($TID,GetMicroTime()+100,__FUNCTION__,array("task"=>"delete"));
			}		
			break;
		case "done":
			ProxyRelease();
			if($p['result'])
			{
				QueueThread($TID,0,__FUNCTION__,array("task"=>"delete"));
			}
			else
			{
				$res = CheckMakePostResult($p);
				if ($res[0] == PostResult_WrongPassw OR $res[0] == PostResult_OK)
				{
					ReleaseThread(array("result"=>$res,"task"=>"deleted"));
				}
				else
				{
					QueueThread($TID,0,__FUNCTION__,array("task"=>"delete"));
				}
			}		
			break;
	}
}
function GetCaptcha($TID,$p)
{
	global $Threads,$ThreadProxy,$ThreadID,$args,$cookies,$proxy,$useragents,$CaptchaExtension,$path,$thread,$v;
	switch ($p['task'])
	{
		case "init":
			$Threads[$TID]['v'] = '';
			$v      =& $Threads[$TID]['v'];
			$v['url'] = GetChanCaptchaUrl($thread,$args['board']);
		case "get":
			DoHTTPRequestPM(array(
				'url'           => $v['url'],
				'ref'           => GetPageUrl(0,$args['board']),
				'cookies'       => GetCookies($cookies),
				'proxytype'     => $proxy['proxytype'],
				'proxy'         => $proxy['proxy'],
				'timeout'       => $args['timeout'],
				'ua'            => $useragents[$args['user-agent']],
				'params'        => array("task"=>"done1"),
				'debug'         => ($args['debug']>2)?($args['debug']-2):0,
			));
			break;
		case "done1":
			if ($p['result'] OR !strpos($p['header'],'image'))
			{
				if (ProxyReportError())
				{
					$p['task']='cerror';
					ReleaseThread($p);
				}
				else
				{
					QueueThread($TID,0,__FUNCTION__,array('task'=>'get'));
				}				
			}
			else
			{
				$fn=$path."tmp/captcha_".$ThreadID.floor(microtime(1)*100).".".$CaptchaExtension;
				file_put_contents($fn,$p['body']);
				CallThread("DecodeCaptcha",array('img'=>$fn),0,'captcha');
			}
			break;
		case "captcha":
			ReleaseThread($p);
			break;
	}
}
function MakePost($TID,$p)
{
	global $thread,$pic,$text,$password,$cookies,$captcha,$v,$Version,$Threads,$ThreadProxy,$ThreadID,$args,$useragents,$proxy,$FailedCaptchas;
	switch($p['task'])
	{
		case "init":
			$Threads[$TID]['v'] = '';
			$v      =& $Threads[$TID]['v'];
		case "post":
			if ($args['captcha'] AND !strlen($captcha))
			{
				CallThread("GetCaptcha",array("thread"=>$thread,"proxy"=>$proxy,"cookies"=>$cookies));
				break;
			}
		case "captcha":
			$v['url'] = GetChanPostUrl($args['board']);
			if (isset($p['captcha']))
				$captcha = $p['captcha'];
			if ($args['captcha'] AND $args['say-captcha'] AND strlen($text))
			{
				$text.="\r\nCaptcha:$captcha";
			}
			if ($args['credits'] AND strlen($text))
			{
				$text.="\r\n\r\nChanUltimateWiper v.{$Version}";
			}
			$data = GetChanPostFields($thread,isset($args['sage']),$text,$pic,$password,$captcha);
			EchoMsgDebug("MakePost() @ $url for thread $thread pic $pic text $text pass $password captcha $captcha proxy $proxy[proxy] $proxy[proxytype]",2);		
			DoHTTPRequestPM(array(
				'url'           => $v['url'],
				'data'		=> $data,
				'ref'           => GetPageUrl(0,$args['board']),
				'cookies'       => GetCookies($cookies),
				'proxytype'     => $proxy['proxytype'],
				'proxy'         => $proxy['proxy'],
				'timeout'       => $args['timeout'],
				'ua'            => $useragents[$args['user-agent']],
				'params'        => array("task"=>"done"),
				'debug'         => ($args['debug']>2)?($args['debug']-2):0,
			));
			break;		
		case "cerror":
			$res = array(PostResult_HTTPErr,0);
		case "done":
			if (!isset($res))
			{
				if ($p['result'] == 28)
				{
					$res = array(PostResult_Timeout,0);
				}
				else if ($p['result'])
				{
					$res = array(PostResult_HTTPErr,0);
				}
				else
				{
					$res = CheckMakePostResult($p);
				}
			}
			if ($res[0] == PostResult_CaptchaWrong)
				$FailedCaptchas++;
			ReleaseThread(array("result"=>$res[0],"thread"=>$res[1],"pic"=>$pic,"passord"=>$password,"captcha"=>$captcha,"task"=>"done"));
			break;	
	}
}
$procId = GetProcId();
EchoMsg("Start");

ProcessArgs($argl);
if (is_file($path."chans/".$args['chan'].".php"))
{
	include($path."chans/".$args['chan'].".php");
	EchoMsg("Loaded $args[chan] module.");
}
else
{
	die($path."chans/".$args['chan'].".php does not exist.");
}
ProcessArgs($argl);
if (is_file($path."modes/".$args['mode'].".php"))
{
	include($path."modes/".$args['mode'].".php");
	EchoMsg("Using $args[mode] mode.");
}
else
{
	die($path."modes/".$args['mode'].".php does not exist.");
}
ProcessArgs($argl);
if (isset($args['captcha']))
{
	if (is_file($path."captcha/".$args['captcha'].".php"))
	{
		include($path."captcha/".$args['captcha'].".php");
		EchoMsg("Using $args[captcha] anti-captcha.");
	}
	else
	{
		die($path."captcha/".$args['captcha'].".php does not exist.");
	}
	ProcessArgs($argl);
}
if ($args['help'])
	PrintHelp($argl);

$use_sets = explode(",",$args['post-set']);

foreach ($use_sets as $i=>$set)
{
	if (is_dir($set))
	{
		$spath = $set;
	}
	else if (is_dir($path."sets/$set"))
	{
		$spath = $path."sets/$set";
	}
	else
	{
		die("Incorrect set specified - $set !");
	}
	$f = scandir($spath);
	$PostSets[$set]=array("path"=>$spath,"pics"=>array(),"text"=>array());
	foreach($f as $i => $j)
	{
		$e = explode('.',$j);
		$e = strtolower(end($e));
		if ($e == 'jpg' OR $e =='jpeg' OR $e == 'gif' OR $e == 'png')
		{
			$PostSets[$set]["pics"][]=$j;
		}
	}
	if (is_file($spath."/set.ini"))
	{
		$f = file($spath."/set.ini");
		$m = 0;
		foreach ($f as $i => $l)
		{
			$l = str_replace(array("\r\n","\r","\n"),array("","",""),$l);
			if ($l == "[text]")
			{
				$m = 2;
			}
			else if ($l{0} == "#")
			{
				$m = $m;
			}
			else if ($m == 2)
			{
				$l = str_replace(array('\r\n','\r','\n','\t'),array("\r\n","\r","\n","\t"),$l);
				$PostSets[$set]["text"][]=$l;
			}
		}
	}
	EchoMsg("$set set is loaded, ".count($PostSets[$set]["pics"])." pics / ".count($PostSets[$set]["text"])." posts.");
}


AddThread("Proxies",'ProxyLoad');

AddThread("Main",$args['mode']."Main");

DoThreading();

EchoMsg("End.");
?>
																

